package manage.actions.rbac;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import manage.actions.ManageAction;
import manage.commons.annontations.RequiredLogin;
import manage.commons.annontations.SuperManager;
import manage.commons.utils.CommonUtil;
import manage.modules.action.model.ActionUri;
import manage.modules.action.service.ActionUriService;
import manage.modules.menu.model.Menu;
import manage.modules.menu.model.MenuFolders;
import manage.modules.menu.service.MenuService;
import manage.modules.rbac.model.ActionOfMenu;
import manage.modules.rbac.model.ActionOfRange;
import manage.modules.rbac.model.ActionOfRole;
import manage.modules.rbac.service.RBACService;
import manage.modules.rbac.util.RBACUtil;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Result;

/**
 * 权限管理
 * 
 * @author dongji
 * @date 2012-9-6 下午03:28:14
 */
@RequiredLogin
@SuperManager
public class RBACAction extends ManageAction {

	private static final long serialVersionUID = 2756334895537618068L;
	private RBACService rbacService;
	private MenuService menuService;
	private ActionUriService actionUriService;
	private Menu menu;
	private ActionUri actionUri;
	private List<Map<String, Object>> dataList;
	private Integer[] menuIds;
	private Integer[] actionIds;
	private Integer[] rangeIds;
	private Integer roleId;
	private String operatorMsg;

	@Override
	@Action(value = "rbac-forward", results = {
			@Result(name = "uri", location = "/rbac/menu-action-list.jsp"),
			@Result(name = "range", location = "/rbac/action-range-list.jsp") })
	public String forwardAddOrUpdatePage() {
		if (StringUtils.equals("menu", operationType)) {
			menu = menuService.select(menu.getMenuId());
			dataList = rbacService.listActionOfMenuByMenuId(menu.getMenuId());
			request.setAttribute("allActionUri", rbacService.listAllActionUri());
			return "uri";
		} else if (StringUtils.equals("actionuri", operationType)) {
			actionUri = actionUriService.select(actionUri.getActionId());
			dataList = rbacService.listActionOfRangeByActionId(actionUri
					.getActionId());
			request.setAttribute("allActionRange",
					rbacService.listAllActionRange());
		}
		return "range";
	}

	/**
	 * 菜单跟操作之间的关系处理
	 * 
	 * @return
	 * @throws Exception
	 */
	@Action(value = "edit-menu-with-action", results = { @Result(name = SUCCESS, location = "/rbac/menu-action-list.jsp") })
	public String editMenuWithAction() throws Exception {
		rbacService.deleteActionUriByMenuId(menu.getMenuId());
		if (ArrayUtils.isNotEmpty(actionIds)) {
			for (Integer actionId : actionIds) {
				ActionOfMenu aom = new ActionOfMenu();
				aom.setMenuId(menu.getMenuId());
				aom.setActionId(actionId);
				rbacService.menuAddActionUri(aom);
			}
		}
		request.setAttribute("operatorType", 1);
		request.setAttribute("operatorMsg", "操作成功");
		return SUCCESS;
	}

	/**
	 * 操作跟操作范围之间的关系处理
	 * 
	 * @return
	 * @throws Exception
	 */
	@Action(value = "edit-action-with-range", results = { @Result(name = SUCCESS, location = "/rbac/action-range-list.jsp") })
	public String editActionWithRange() throws Exception {
		rbacService.deleteActionRangeByActionId(actionUri.getActionId());
		if (ArrayUtils.isNotEmpty(rangeIds)) {
			for (Integer rangeId : rangeIds) {
				ActionOfRange aor = new ActionOfRange();
				aor.setActionId(actionUri.getActionId());
				aor.setRangeId(rangeId);
				aor.setIsRadio(super.getParameterForInt("isRadio_" + rangeId));
				rbacService.actionAddActionRange(aor);
			}
		}
		request.setAttribute("operatorType", 1);
		operatorMsg = "操作成功";
		return SUCCESS;
	}

	/**
	 * 权限处理入口
	 * 
	 * @return
	 */
	@Action("rbac-setting-input")
	public String rabcSettingInput() {
		request.setAttribute("roleRbacLayout",
				rbacService.listRBACLayoutByRoleId(roleId));
		request.setAttribute("rbacLayout", rbacService.listRBACLayout());
		return SUCCESS;
	}

	/**
	 * 权限处理
	 * 
	 * @return
	 * @throws Exception
	 */
	@Action(value = "rbac-setting", results = { @Result(name = SUCCESS, type = "redirect", location = "rbac-setting-input.do?roleId=${roleId}&operatorMsg=${operatorMsg}") })
	public String rabcSetting() throws Exception {
		List<MenuFolders> menuFolders = rbacService.listMenuByRoleId(roleId);
		List<Integer> roleMenuIds = RBACUtil.processMFToIdList(menuFolders);
		List<Integer> reduceMenuIds = CommonUtil.operatorReduceValue(
				roleMenuIds, menuIds);
		List<Integer> addMenuIds = CommonUtil.operatorAddValue(menuIds,
				roleMenuIds);

		// 删除菜单可见权限
		if (CollectionUtils.isNotEmpty(reduceMenuIds)) {
			for (Integer menuId : reduceMenuIds) {
				rbacService.deleteMenuOfRole(menuId, roleId);
			}
		}
		// 增加菜单可见权限
		if (CollectionUtils.isNotEmpty(addMenuIds)) {
			for (Integer menuId : addMenuIds) {
				rbacService.insertMenuOfRole(menuId, roleId);
			}
		}
		List<ActionOfRole> actionOfRoles = rbacService
				.listActionOfRoleByRoleId(roleId);
		List<Integer> roleActionIds = RBACUtil.processARToIdList(actionOfRoles);
		List<Integer> reduceActionIds = CommonUtil.operatorReduceValue(
				roleActionIds, actionIds);
		List<Integer> addActionIds = CommonUtil.operatorAddValue(actionIds,
				roleActionIds);
		// 删除操作
		if (CollectionUtils.isNotEmpty(reduceActionIds)) {
			for (Integer actionId : reduceActionIds) {
				rbacService.deleteActionOfRole(actionId, roleId);
			}
		}
		// 增加操作
		if (CollectionUtils.isNotEmpty(addActionIds)) {
			for (Integer actionId : addActionIds) {
				String[] rangeIds = super.getParameterValues("rangeId_"
						+ actionId);
				if (ArrayUtils.isNotEmpty(rangeIds)) {
					int[] rIds = CommonUtil.evalIntArray(rangeIds);
					for (int id : rIds) {
						rbacService.insertActionOfRole(actionId, roleId, id);
					}
				} else {
					rbacService.insertActionOfRole(actionId, roleId, 0);
				}
			}
		}
		// 没有发生改变的操作，但是需要判断数据范围的值是否发生改变
		List<Integer> noChangeActionIds = CommonUtil.operatorNoChangeValue(
				roleActionIds, actionIds);
		if (CollectionUtils.isNotEmpty(noChangeActionIds)) {
			List<Integer> operatedId = new ArrayList<Integer>();
			for (ActionOfRole actionOfRole : actionOfRoles) {
				Integer actionId = actionOfRole.getActionId();
				if (noChangeActionIds.contains(actionOfRole.getActionId())
						&& !operatedId.contains(actionOfRole.getActionId())) {
					String[] rangeIds = super.getParameterValues("rangeId_"
							+ actionId);
					Integer[] rIds = ArrayUtils.toObject(CommonUtil
							.evalIntArray(rangeIds));
					List<Integer> dbRangeIds = rbacService
							.listRangIdByActionAndRole(actionId, roleId);
					List<Integer> reduceRangeIds = CommonUtil
							.operatorReduceValue(dbRangeIds, rIds);
					List<Integer> addRangeIds = CommonUtil.operatorAddValue(
							rIds, dbRangeIds);
					if (CollectionUtils.isNotEmpty(reduceRangeIds)) {
						for (Integer id : reduceRangeIds) {
							if (!StringUtils.equals("0", String.valueOf(id))) {
								rbacService
										.deleteActionOfRole(new ActionOfRole(
												roleId, actionId, id));
							}
						}
					}
					if (CollectionUtils.isNotEmpty(addRangeIds)) {
						for (Integer id : addRangeIds) {
							rbacService
									.insertActionOfRole(actionId, roleId, id);
						}
					}
				}
			}
		}
		operatorMsg = "操作成功";
		return SUCCESS;
	}

	/**
	 * 角色可见菜单入口
	 * 
	 * @return
	 */
	@Action("role-menu-input")
	public String roleMenuInput() {
		request.setAttribute("roleMenuFolders",
				menuService.listMenuByRoleId(roleId));
		return SUCCESS;
	}

	/**
	 * 角色可见菜单权限编辑
	 * 
	 * @return
	 * @throws Exception
	 */
	@Action(value = "role-menu", results = { @Result(name = SUCCESS, type = "redirect", location = "role-menu-input.do?roleId=${roleId}&operatorMsg=${operatorMsg}") })
	public String roleMenu() throws Exception {
		List<MenuFolders> menuFolders = menuService.listMenuByRoleId(roleId);
		if (CollectionUtils.isNotEmpty(menuFolders)) {
			for (MenuFolders menuFolder : menuFolders) {
				for (Menu childMenu : menuFolder.getChilds()) {
					int isDisplay = super.getParameterForInt("isDisplay_"
							+ childMenu.getMenuId());
					if (isDisplay == -1 && childMenu.getParentId() != 0) {
						rbacService.deleteMenuOfRole(childMenu.getMenuId(),
								roleId);
					}
				}
			}
			operatorMsg = "操作成功";
		} else {
			operatorMsg = "操作无效";
		}
		return SUCCESS;
	}

	public void setRbacService(RBACService rbacService) {
		this.rbacService = rbacService;
	}

	public List<Map<String, Object>> getDataList() {
		return dataList;
	}

	public void setMenu(Menu menu) {
		this.menu = menu;
	}

	public void setActionUri(ActionUri actionUri) {
		this.actionUri = actionUri;
	}

	public void setMenuService(MenuService menuService) {
		this.menuService = menuService;
	}

	public Menu getMenu() {
		return menu;
	}

	public ActionUri getActionUri() {
		return actionUri;
	}

	public void setActionUriService(ActionUriService actionUriService) {
		this.actionUriService = actionUriService;
	}

	public void setActionIds(Integer[] actionIds) {
		this.actionIds = actionIds;
	}

	public void setRangeIds(Integer[] rangeIds) {
		this.rangeIds = rangeIds;
	}

	public Integer getRoleId() {
		return roleId;
	}

	public void setRoleId(Integer roleId) {
		this.roleId = roleId;
	}

	public String getOperatorMsg() {
		return operatorMsg;
	}

	public void setOperatorMsg(String operatorMsg) {
		this.operatorMsg = operatorMsg;
	}

	public void setMenuIds(Integer[] menuIds) {
		this.menuIds = menuIds;
	}

}
